#ifndef LISTAIMP_CPP
#define LISTAIMP_CPP

//#include "Constantes.h"
#include "ListaImp.h"
#include <iostream>
using namespace std;

template <class T>
ListaImp<T>::ListaImp(){
	primero=NULL;
	tamActual = 0;
}

template <class T>
ListaImp<T>::~ListaImp(){
	BorrarTodos();
}

template <class T>
ListaImp<T>::ListaImp(const T& d, Puntero<nodoListaImp<T> > sig)
{
	primero->dato = d;
	primero->siguiente = sig;
	tamActual = 1;
}

template <class T>
void ListaImp<T>::Agregar(const T& e)
{
	AgregarEn(e, Largo());
}
template <class T>
void ListaImp<T>::AgregarEn(const T& e, Natural posicion){
	assert ((posicion>= 0) && (posicion <= Largo()+1));
	if (this->EstaVacia()){
		primero = new nodoListaImp<T>;	
		primero->dato = e;
		primero->siguiente = NULL;
	}
	else{
		Puntero<nodoListaImp<T> > nuevo = new nodoListaImp<T>;
		nuevo->dato = e;
		if(posicion == 0){// tengo que insertar al principio
			nuevo->siguiente=primero;
			primero=nuevo;			
		}
		else{// insertar en otra posicion 
			int contador = 0;
			Puntero<nodoListaImp<T> > iterador = new nodoListaImp <T>;
			iterador=primero;
			bool inserte = false;
			while ((!inserte)&&(contador <= (int)Largo())){
				if((int)posicion == contador +1){ //la proxima es la posicion donde tengo que insertar
					nuevo->siguiente = iterador->siguiente;
					iterador->siguiente = nuevo;
					inserte = true;
				}
				else{
					contador++;
					iterador = iterador->siguiente;
				}				
			}
		}
	}		
	tamActual = tamActual + 1;
}

template <class T>
void ListaImp<T>::BorrarTodos()
{
	while (Largo() > 0)
		Borrar(0);
}

template <class T>
void ListaImp<T>::Borrar(Natural pos) 
{
	assert ((pos>= 0) && (pos < Largo()));
	if (pos==0){
		Puntero<nodoListaImp <T> > nuevo = this->primero->siguiente ;
		this->primero = nuevo;
	}
	else{
		Puntero<nodoListaImp<T> > iterador = this->primero;
		Puntero<nodoListaImp <T> > anterior ;
		while ((int)pos <= this->tamActual)
		{
			anterior = iterador;
			if (iterador != NULL)
				iterador = iterador->siguiente;
			pos++;
		}
		if (anterior != NULL){
			Puntero<nodoListaImp <T> > nuevo = new nodoListaImp<T>;
			if (iterador !=NULL)
				nuevo = iterador->siguiente;
			else
				nuevo = NULL;
			anterior ->siguiente = nuevo;
			
		}
	}
	tamActual--;
}
template <class T>
Puntero<Lista<T>> ListaImp<T>::Clonar() 
{
	Puntero<Lista<T> > copiaLista = new ListaImp<T>();
	Puntero<nodoListaImp <T> > iterador = primero;
	while (iterador!= NULL){
		T nuevo = iterador->dato;
		copiaLista->Agregar(nuevo);
		iterador =iterador->siguiente;
	}
	return copiaLista;
}

template <class T>
T& ListaImp<T>::ElementoEn(Natural pos) const 
{
	assert ((pos>= 0) && (pos <= Largo()));
	Puntero<nodoListaImp <T> > iterador = new nodoListaImp<T>;
	Puntero<nodoListaImp <T> > retorno = new nodoListaImp<T>;
	iterador = primero;
	int contador =0;
	bool encontre = false;
	while ((contador <= (int)Largo())&&(!encontre)){
		if((int)pos == contador){
			retorno =  iterador;
			encontre = true;
		}
		else{			
			contador ++;
			iterador = iterador->siguiente;
		}
	}
	return retorno->dato;
}

/*
template <class T>
T& ListaImp<T>::ElementoEn(Natural pos) const 
{
	assert ((pos>= 0) && (pos <= Largo()));
	Puntero<nodoListaImp <T> > iterador = new nodoListaImp<T>;
	iterador = primero;
	int contador =0;
	bool encontre = false;
	while ((contador <= (int)Largo())&&(!encontre)){
		if((int)pos == contador){
			return iterador->dato;
			encontre = true;
		}
		else{			
			contador ++;
			iterador = iterador->siguiente;
		}
	}
}*/

template <class T>
T& ListaImp<T>::Primero() const
{
	assert(Largo() > 0);
	return ElementoEn(0);
}

template <class T>
T& ListaImp<T>::Ultimo() const
{
	assert(Largo() > 0);
	return ElementoEn(Largo() - 1);
}

template <class T>
Natural ListaImp<T>::Largo() const 
{
	return this->tamActual;
}


template <class T>
bool ListaImp<T>::EstaLlena() const 
{
	return (this->tamActual == this->tamMax);

}

template <class T>
bool ListaImp<T>::EstaVacia() const
{
	return Largo() == 0;
}

template <class T>
bool ListaImp<T>::esVacio(const Puntero<nodoListaImp<T> > n)
{
	return primero == NULL;
}

template <class T>
Puntero<Iterador<T> > ListaImp<T>::ObtenerIterador() const {
    return new IteradorImp<T>(*this);
}

template <class T>
bool ListaImp<T>::Existe(const T& e) const{
	bool retorno = false;
	Puntero<nodoListaImp <T> > iterador = new nodoListaImp<T>;
	iterador = primero;
	int contador = 1;
	bool encontre = false;
	while((contador<=Largo())&&(!encontre)){
		if (iterador->dato == e){
			encontre = true;
			retorno= true;
		}
		else{
			contador ++;
			iterador = iterador->siguiente;
		}
	}
	return retorno;
}


#endif
